package com.biye.api.tool.security.service.impl;

import com.base.common.edu.entity.Staff;
import com.base.common.edu.entity.Student;
import com.base.common.edu.mapper.StaffMapper;
import com.base.common.edu.mapper.StudentMapper;
import com.biye.api.tool.security.mapper.SecurityMapper;
import com.biye.api.tool.security.pojo.UserDetail;
import com.biye.api.tool.security.service.UserDetailService1;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author Maple.Chen
 * @Description 这里根据用户id, 即学号或工号来查询用户的角色
 *              学生的角色列表是代码固定的，如果想要扩展，只能修改当前类。教师的角色是通过数据库查询的，属于动态，调整数据库数据即可。
 * @Date 16:50 2021/3/7
 **/
@Service
public class UserDetailServiceImpl implements UserDetailsService, UserDetailService1 {

    @Resource
    private StudentMapper studentMapper;

    @Resource
    private StaffMapper staffMapper;

    @Resource
    private SecurityMapper securityMapper;

    protected static List<String> stuRoleList = new ArrayList<>();
    static {
        stuRoleList.add("common");
        stuRoleList.add("student");
        // 如果数据库中role_code字段，每条记录都没有“ROLE_”前缀，可以执行以下语句,若已经有前缀，可以注释
        stuRoleList = stuRoleList.stream().map(rc -> "ROLE_" + rc).collect(Collectors.toList());
    }

    @Override
    public UserDetails loadUserByUsername(String userIdAndType) throws UsernameNotFoundException {
        String[] user_info_arr = userIdAndType.split("@");
        String user_id = user_info_arr[0];  // sno or tno
        String user_type = user_info_arr[1];  // stu or tea
        UserDetail u = null;
        if ( "stu".equals(user_type) ){
            Student student = studentMapper.queryStudentById(user_id);
            if (student == null )
                throw new RuntimeException("用户不存在");
            // 用户角色列表
            List<GrantedAuthority> grantedAuthorityList = new ArrayList<>() ;
            /*
             * Spring Boot 2.0 版本踩坑
             * 数据库ROLE_CODE字段每一条记录必须要 ROLE_ 前缀， 因为 hasRole("LEVEL1")判断时会自动加上ROLE_前缀变成 ROLE_LEVEL1 ,
             * 如果不加前缀一般就会出现403错误，如果使用hasAuthority("ROLE_LEVEL1").
             * 在给用户赋权限时,数据库存储必须是完整的权限标识ROLE_LEVEL1
             */
            if (stuRoleList != null && stuRoleList.size()>0){
                for (String role : stuRoleList){
                    grantedAuthorityList.add(new SimpleGrantedAuthority(role)) ;
                }
            }
            // 判断学生用户的账号是否在激活状态
            int status = student.getActivateStatus();
            boolean enable = status == 1 ? true : false;
            u =new UserDetail(student.getStuID(), student.getSno(), null, enable, grantedAuthorityList);
        }
        if ( "tea".equals(user_type) ){
            Staff staff = staffMapper.queryStaffById(user_id);
            if (staff == null )
                throw new RuntimeException("用户不存在");
            // 用户角色，确保表Role字段数据都有ROLE_前缀
            List<String> roleList = queryRoleListByUsername(user_id);
            List<GrantedAuthority> grantedAuthorityListTea = new ArrayList<>() ;
            if (roleList != null && roleList.size()>0){
                for (String role : roleList){
                    grantedAuthorityListTea.add(new SimpleGrantedAuthority(role)) ;
                }
            }
            // 判断职工用户的账号是否在激活状态
            int status = staff.getActivateStatus();
            boolean enable = status == 1 ? true : false;
            u =new UserDetail(staff.getStaffId(), staff.getTno(), null, enable, grantedAuthorityListTea);
        }
        return u;
    }

    // 通过用户id，查看当前职工的角色及其所属组的角色之和，使用union对联合查询结果去重
    @Override
    public List<String> queryRoleListByUsername(String staff_id) {
        return this.securityMapper.findRoleListByUserId(staff_id);
    }
}
